//
//  LYMViewAnimation.m
//  LYMViewAnimation
//
//  Created by lim on 2019/6/4.
//  Copyright © 2019年 lim. All rights reserved.
/*
 UIViewAutoresizingNone
 
 不会随父视图的改变而改变
 UIViewAutoresizingFlexibleLeftMargin
 
 自动调整view与父视图左边距，以保证右边距不变
 UIViewAutoresizingFlexibleWidth
 
 自动调整view的宽度，保证左边距和右边距不变
 UIViewAutoresizingFlexibleRightMargin
 
 自动调整view与父视图右边距，以保证左边距不变
 UIViewAutoresizingFlexibleTopMargin
 
 自动调整view与父视图上边距，以保证下边距不变
 UIViewAutoresizingFlexibleHeight
 
 自动调整view的高度，以保证上边距和下边距不变
 UIViewAutoresizingFlexibleBottomMargin
 
 自动调整view与父视图的下边距，以保证上边距不变
 **/

//传进来的视图 ---> 加到背景LYMCustomView上 ---> 加到遮罩上LYMMaskView  --->然后加到LYMViewController的View上

#import "LYMViewAnimation.h"

#define MXAS_SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
#define MXAS_SCREEN_WIDTH  ([UIScreen mainScreen].bounds.size.width)

/** 自定义View */
@interface LYMCustomView : UIView
@property (nonatomic, assign) CALayer *styleLayer;
@property (nonatomic, strong) LYMAnimationConfig *config;

@end

/** 遮罩视图 */
@interface LYMMaskView : UIView
@property (nonatomic, strong) UIColor *maskColor;
@property (nonatomic, strong) LYMAnimationConfig *config;

@end

/** 弹出的控制器 */
@interface LYMViewController: UIViewController
@property (weak, nonatomic) LYMMaskView *maskView;
@property (nonatomic, strong) LYMAnimationConfig *config;

@end

@interface LYMViewAnimation ()
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, weak) LYMViewController *viewController;
@property (nonatomic, weak) LYMCustomView *containerView;
@property (nonatomic, strong) LYMAnimationConfig *config;

@end

/** 动画配置 */
@implementation LYMAnimationConfig

- (instancetype)init {
    if (self = [super init]) {
        self.lym_AnimationType = LYMAnimationTypeBottom;
        self.lym_MaskViewColor = [UIColor blackColor];
        self.lym_IsMaskViewClickDiss = YES;
        self.lym_MaskColorType = LYMColorTypeGradient;
        self.lym_BackColor = [UIColor blueColor];
        self.lym_IsShadow = NO;
        self.lym_ShowViewColor = [UIColor whiteColor];
    }
    return self;
}

@end

@implementation LYMViewAnimation

+ (LYMViewAnimation *)shareLYMViewAnimation {
    static LYMViewAnimation *instance = nil;
    static dispatch_once_t onceToken;
  
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init {
    if (self = [super init]) {
    }
    return self;
}

- (CGRect)recalculatePositionWithRect:(CGRect)rect {
    CGRect maskViewRect = rect;
    if (_config.lym_AnimationType == LYMAnimationTypeTop) {
        maskViewRect.origin.x = 0;
        maskViewRect.origin.y = -MXAS_SCREEN_HEIGHT;
    }
    
    if (_config.lym_AnimationType == LYMAnimationTypeLeft) {
        maskViewRect.origin.x = -MXAS_SCREEN_WIDTH;
        maskViewRect.origin.y = 0;
    }
    
    if (_config.lym_AnimationType == LYMAnimationTypeBottom) {
        maskViewRect.origin.x = 0;
        maskViewRect.origin.y = MXAS_SCREEN_HEIGHT;
        
    }
    
    if (_config.lym_AnimationType == LYMAnimationTypeRight) {
        maskViewRect.origin.x = MXAS_SCREEN_WIDTH;
        maskViewRect.origin.y = 0;
    }
    
    if (_config.lym_AnimationType == LYMAnimationTypeZoom) {
        CGFloat padding = 0;
        //该结构体的应用是以原rect为中心，再参考dx，dy，进行缩放或者放大。正值表示缩小
        CGRect tempRect = CGRectInset(rect, -padding, -padding);
        tempRect.origin.x = tempRect.origin.y = 0;
        tempRect.origin.x = round(CGRectGetMidX(self.window.bounds) - CGRectGetMidX(tempRect));
        tempRect.origin.y = round(CGRectGetMidY(self.window.bounds) - CGRectGetMidY(tempRect));
        maskViewRect = tempRect;
    }
    return maskViewRect;
}

- (void)lym_ShowPresentView:(UIView *)presentView withConfg:(LYMAnimationConfig *)config {
    NSAssert([NSThread isMainThread], @"It needs to be called in the main thread");
    NSAssert(presentView.frame.size.height != 0 && presentView.frame.size.width != 0, @"宽高不能为空");
    NSAssert(config != nil, @"config 不能为nil");
    _config = config;
    presentView.backgroundColor = config.lym_ShowViewColor;
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.window.opaque = NO;
  
    LYMViewController *viewController  = [LYMViewController new];
    viewController.config = self.config;
    self.window.rootViewController = viewController;
    self.viewController = viewController;
    
    CGRect maskViewRect = [self recalculatePositionWithRect:presentView.frame];
    
    LYMCustomView *containerView = [[LYMCustomView alloc] initWithFrame:maskViewRect];
    containerView.config = self.config;
 
    
    containerView.autoresizingMask =  UIViewAutoresizingFlexibleRightMargin;
    containerView.layer.rasterizationScale = [[UIScreen mainScreen] scale];
    //修改后的frame
    presentView.frame = presentView.bounds;
    //传进来的View加到背景上
    [containerView addSubview:presentView];
    //把背景View加到控制View上
    [viewController.view addSubview:containerView];
    
    self.containerView = containerView;
    
    [self.window makeKeyAndVisible];
    
    viewController.maskView.alpha = 0;
    
    [UIView animateWithDuration:0.5 animations:^{
        viewController.maskView.alpha = 1;
    }];
    
    containerView.alpha = 0;
    /*
     栅格化：layer设置shouldRasterize＝YES之后，
     会把被光栅化的图层保存成位图并缓存起来其中圆角或者阴影之类的效果也是直接保存到位图当中，
     当需要渲染到屏幕上的时候只需要到缓存中去取对应的位图进行显示就行了，加快了整个渲染过程。
     **/
    containerView.layer.shouldRasterize = YES;
    
    if (config.lym_AnimationType == LYMAnimationTypeTop) {
        [UIView animateWithDuration:0.5 animations:^{
            containerView.alpha = 1;
            CGRect frame = containerView.frame;
            frame.origin.y = 0;
            containerView.frame = frame;
        } completion:nil];
    }
    
    
    if (config.lym_AnimationType == LYMAnimationTypeLeft) {
        [UIView animateWithDuration:0.5 animations:^{
            containerView.alpha = 1;
            CGRect frame = containerView.frame;
            frame.origin.x = 0;
            containerView.frame = frame;
            
        } completion:nil];
        
    }
    
    if (config.lym_AnimationType == LYMAnimationTypeBottom) {
        [UIView animateWithDuration:0.5 animations:^{
            containerView.alpha = 1;
            CGRect frame = containerView.frame;
            frame.origin.y = MXAS_SCREEN_HEIGHT - containerView.frame.size.height;
            containerView.frame = frame;
        } completion:nil];
 }
    
    if (config.lym_AnimationType == LYMAnimationTypeRight) {
        [UIView animateWithDuration:0.5 animations:^{
            containerView.alpha = 1;
            CGRect frame = containerView.frame;
            frame.origin.x = MXAS_SCREEN_WIDTH - containerView.frame.size.width;
            containerView.frame = frame;
        } completion:nil];
        
    }
    
    if (config.lym_AnimationType == LYMAnimationTypeZoom) {
    
        containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0, 0);
        
        [UIView animateWithDuration:0.3 animations:^{
            containerView.alpha = 1;
            containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
        } completion:^(BOOL finished) {
            
            [UIView animateWithDuration:0.2 animations:^{
                containerView.alpha = 1;
                containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9);
                
            } completion:^(BOOL finished) {
                
                [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                    containerView.alpha = 1;
                    containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
                } completion:^(BOOL finished) {
                    containerView.layer.shouldRasterize = NO;
                }];
                
            }];
            
        }];
    }
   
}

- (void)close {
    [self hideAnimated:self.config.lym_AnimationType withCompletionBlk:nil];
}

- (void)lym_closeWithComplete:(void(^)(void))complete {
    [self hideAnimated:self.config.lym_AnimationType withCompletionBlk:complete];
}

- (void)hideAnimated:(LYMAnimationType)animationType  withCompletionBlk:(void(^)(void))completionBlk {
    if (self.containerView == nil) {
        return;
    }
    
     if (animationType == LYMAnimationTypeZoom) {
        [UIView animateWithDuration:0.7 animations:^{
            self.viewController.maskView.alpha = 0;
        }];
        
        self.containerView.layer.shouldRasterize = YES;
        [UIView animateWithDuration:0.4 animations:^{
            self.containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
        } completion:^(BOOL finished) {
            // UIViewAnimationOptionCurveEaseOut时间曲线函数，由快到慢(快入缓出)
            [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                self.containerView.alpha = 0;
            } completion:^(BOOL finished) {
                [self cleanUp];
                if (completionBlk) {
                    completionBlk();
                }
            }];
        }];
     }
    
    if (animationType == LYMAnimationTypeNormal) {
         [self cleanUp];
     }
   
    if (animationType == LYMAnimationTypeTop) {
        [UIView animateWithDuration:0.4 animations:^{
            CGRect frame = self.containerView.frame;
            frame.origin.y = -MXAS_SCREEN_HEIGHT;
            self.containerView.frame = frame;
            self.containerView.alpha = 0.01;
        } completion:^(BOOL finished) {
            [self cleanUp];
        }];
    }
    
    if (animationType == LYMAnimationTypeLeft) {
        [UIView animateWithDuration:0.4 animations:^{
            CGRect frame = self.containerView.frame;
            frame.origin.x = -MXAS_SCREEN_HEIGHT;
            self.containerView.frame = frame;
            self.containerView.alpha = 0.01;
        } completion:^(BOOL finished) {
            [self cleanUp];
        }];
    }
    
    if (animationType == LYMAnimationTypeBottom) {
        [UIView animateWithDuration:0.4 animations:^{
            CGRect frame = self.containerView.frame;
            frame.origin.y = MXAS_SCREEN_HEIGHT;
            self.containerView.frame = frame;
            self.containerView.alpha = 0.01;
        } completion:^(BOOL finished) {
            [self cleanUp];
        }];
    }
    
    if (animationType == LYMAnimationTypeRight) {
        [UIView animateWithDuration:0.4 animations:^{
            CGRect frame = self.containerView.frame;
            frame.origin.x = MXAS_SCREEN_HEIGHT;
            self.containerView.frame = frame;
            self.containerView.alpha = 0.01;
        } completion:^(BOOL finished) {
            [self cleanUp];
        }];
    }
}

- (void)cleanUp {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [self.containerView removeFromSuperview];
    [[[[UIApplication sharedApplication] delegate] window] makeKeyWindow];
    [self.window removeFromSuperview];
    self.window = nil;
}

- (void)dealloc {
    [self cleanUp];
}
@end


@implementation LYMViewController

- (void)loadView {
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor clearColor];
    self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    //创建遮罩视图
    LYMMaskView *maskView = [[LYMMaskView alloc] initWithFrame:self.view.bounds];
    maskView.config = self.config;
    maskView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    maskView.opaque = NO;
    [self.view addSubview:maskView];
    self.maskView = maskView;
}

@end
@implementation LYMCustomView

- (instancetype)initWithFrame:(CGRect)frame  {
    self = [super initWithFrame:frame];
    if (self) {
    }
    return self;
}

- (void)setConfig:(LYMAnimationConfig *)config {
    _config = config;
    if (config.lym_IsShadow == YES) {
        CALayer *styleLayer = [[CALayer alloc] init];
        styleLayer.backgroundColor = config.lym_BackColor.CGColor;

        //设置圆角
        //styleLayer.cornerRadius = 0;
        //投影设置
        styleLayer.shadowColor = [[UIColor blackColor] CGColor];
        /*
         向左偏移10 （-10，0）
         向右偏移10 （10，0）
         向上偏移10 （0，-10）
         向下偏移10 （0，10）
         **/
        //阴影偏移
        styleLayer.shadowOffset = CGSizeMake(10, 10);
        //影子不透明
        styleLayer.shadowOpacity = 0.5;
        //边框设置
        styleLayer.borderWidth = 1;
        styleLayer.borderColor = [UIColor darkGrayColor].CGColor;
        //放大12
        styleLayer.frame = CGRectInset(self.bounds, -2, -2);
        [self.layer addSublayer:styleLayer];
        self.styleLayer = styleLayer;
    }
    self.backgroundColor = config.lym_BackColor;
}

@end

/**
 遮罩视图
 */
@implementation LYMMaskView

- (void)setMaskColor:(UIColor *)maskColor {
    if (maskColor) {
        _maskColor = maskColor;
    }
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    if (self.config.lym_MaskColorType == LYMColorTypeCustom) {
        if (self.config.lym_MaskViewColor) {
         [[UIColor colorWithCGColor:self.config.lym_MaskViewColor.CGColor] set];
        } else {
            [[UIColor colorWithWhite:0.0f alpha:0.55] set];
        }
        CGContextFillRect(context, self.bounds);
        
    } else {//渐变色
        CGContextSaveGState(context);
        size_t gradLocationNum = 2;
        //向量从左到右渐变---->
        CGFloat gradLocations[2] = {0.0f, 1.0f};
        CGFloat gradColors[8] = {0, 0, 0, 0.3,   0, 0, 0, 0.8};
        /*
         CGCradientCreateWithColorComponents函数需要四个参数：
         色彩空间：（Color Space）这是一个色彩范围的容器，类型必须是CGColorSpaceRef.对于这个参数，我们可以传入CGColorSpaceCreateDeviceRGB函数的返回值，它将给我们一个RGB色彩空间。
         颜色分量的数组：这个数组必须包含CGFloat类型的红、绿、蓝和alpha值。数组中元素的数量和接下来两个参数密切。从本质来讲，你必须让这个数组包含足够的值，用来指定第四个参数中位置的数量。所以如果你需要两个位置位置（起点和终点），那么你必须为数组提供两种颜色
         位置数组，颜色数组中各个颜色的位置：此参数控制该渐变从一种颜色过渡到另一种颜色的速度有多快。
         
         位置的数量：这个参数指明了我们需要多少颜色和位置。
         
         */
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationNum);
        CGColorSpaceRelease(colorSpace);
        colorSpace = NULL;
        //渐变中心
        CGPoint gradCenter = CGPointMake(round(CGRectGetMidX(self.bounds)), round(CGRectGetMidY(self.bounds)));
        //渐变半径
        CGFloat gradRadius = MAX(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
        //径向渐变
        CGContextDrawRadialGradient(context, gradient, gradCenter, 0, gradCenter, gradRadius, kCGGradientDrawsAfterEndLocation);
        CGGradientRelease(gradient);
        gradient = NULL;
        CGContextRestoreGState(context);
    }
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    if (self.config.lym_IsMaskViewClickDiss) {
    [[LYMViewAnimation shareLYMViewAnimation] hideAnimated:self.config.lym_AnimationType withCompletionBlk:nil];
    }
    
}
@end
